/*************************************************************************
  Crytek Source File.
  Copyright (C), Crytek Studios, 2001-2010.
 -------------------------------------------------------------------------
  $Id$
  $DateTime$
  
 -------------------------------------------------------------------------
  History:
  - Oct 5th, 2010  : Created by Michelle Martin
 *************************************************************************/

#ifndef __IKTARGET_BASE_H__
#define __IKTARGET_BASE_H__

#if _MSC_VER > 1000
# pragma once
#endif

#include <IIKTargetSystem.h>

// ====================================================


class CIKTarget_Base
{
public:
	CIKTarget_Base(const SIKTargetParams& ikParams, QuatT &startPosition);
	virtual ~CIKTarget_Base() {}

	friend class CIKTargetSystem;

private:

	// ==========================================================
	//   functions to override in derived classes
	// ==========================================================

	//! Update function	
	//! returns the new current world location of the ik target
	virtual QuatT UpdateWorldPos(float frameTime) = 0;

	// ==========================================================

public:
	//! Base Class update function - calls UpdateWorldPos and stores it in m_currentWorldPos
	//! please do not override this function in derived classes, use UpdateWorldPos() instead
	//! this way, the target can be easily retrieved multiple times in a frame, but will
	//! only be calculated once
	//! The offset parameter is being used for offsetting the debug output in x direction.
	//! an offset of -1 will disable the debug output
	void Update(float frameTime, int offset = -1);

	//! call to have the ik target position return to the original end-effector's position (fade out IK)
	void FadeOut(float fadeOutTimeInSecs = 0.3f);

	//! Retrieves the current (blended) world position for the ik target
	const QuatT& GetCurrentWorldPos() const;

	//! Retrieves the unblended world position (only needed for anticipation or lookahead features)
	const QuatT& GetCurrentTargetWorlPos() const;

	//! returns a number (0...1) representing the amount the target is blended in to the final target
	const float GetCurrentBlendVal() const;

	//! returns the current status of the IK Target
	EIK_States GetIKState() const;

	//! returns true if the IK Solver should also align the end effector (as set in the SIKTargetParams)
	const bool GetEndEffectorAlignPolicy() const;

	//! return the IK Limb id of the spine that shall be involved in the IK for this limb (0 if none should be involved)
	const uint64 GetSpinePolicy() const;

	//! Sets a new/updated offset 
	void SetOffset(const QuatT& newOffset);

	//! Returns the current world position for the bone that is the end-effector of the given IK handle 
	//! example: the hand bone for the LftArm01
	static QuatT GetLimbEndeffectorWorldPos( EntityId entityID, uint64 ikHandle );
	//static QuatT GetLimbEndeffectorWorldPos( EntityId entityID, const char* ikHandleName );

	//! Returns the current world position for the bone that is the root of the given IK handle 
	//! example: the shoulder for the LftArm01
	static QuatT GetLimbRootWorldPos( EntityId entityID, uint64 ikHandle );
	QuatT		GetCurrentLimbRootWorldPos();

private:


	QuatT ApplyOffset(const QuatT& worldLoc, float blendVal, Quat blendRot = Quat(IDENTITY));

	void UpdateBlendingIn(float frameTime, int offset = -1);

	void UpdateBlendingOut(float frameTime, int offset = -1);

	void StartLimbAnimation();

	void StopLimbAnimation(float blendOutTime);

	//! timer that is used for various purposes depending on the 
	float		m_blendHelperTime;

	//! position that is used in various purposes depending on the state of the IK
	QuatT		m_blendHelperPos;

	//! current blended world position
	QuatT		m_currentWorldPos;

	//! latest final world pos
	QuatT		m_targetWorldPos;

	//! whether the IK is currently fading in, is fully blended in or is fading out, or it fully blended out
	EIK_States m_currentIKState;

	//! IK Parameters that have been passed in from the code calling IKTargetSystem
	SIKTargetParams m_ikParameters;

};



#endif // __IKTARGET_BASE_H__

